﻿using Bettzueche.RLLibrary.Types;
using System;

namespace AMEE1
{
    /// <summary>
    /// Partitionierung von Entfernungen (in Schritten gemessen).
    /// </summary>
    class Entfernungen : Tiling
    {
        int[] _bereiche;

        /// <summary>
        /// Initializes a new instance of the <see cref="Entfernungen"/> class.<para>
        /// Übergabe der Obergrenzen (inklusive) der Distanzbereichen.</para>
        /// </summary>
        /// <param name="bereiche">The bereiche, zB. {1,2,10,Int32.MaxValue} (muss nicht sortiert sein).<para>
        /// Ergibt die Bereiche ]0.0,1.0], ]1.0, 2.0], usw.</para></param>
        public Entfernungen(params int[] bereiche) {
            _bereiche = new int[bereiche.Length];
            bereiche.CopyTo(_bereiche, 0);
            Array.Sort(_bereiche);
            base.Min = _bereiche[0];
            base.Max = (int)_bereiche.Last();
            base.Partitions = _bereiche.Length;
        }

        /// <summary>
        /// Gets the partition number the specified value lies in.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns>
        /// The partition number the specified value lies in. 
        /// <see cref="Tiling#OutOfBounds" /> if value is less than Min.
        /// </returns>
        public override int GetPartitionNumber(double value) {
            for (int i = 0; i < _bereiche.Length; i++) {
                if (value <= _bereiche[i])
                    return i;
            }
            return Tiling.OutOfBounds;
        }

        /// <summary>
        /// Gets the median of the specified partition number, that is the midpoint of the sub-interval.
        /// </summary>
        /// <param name="partition">The partition index.</param>
        /// <returns>
        /// The median (midpoint) value of the specified partition.
        /// <para>
        /// NegativInfinity, if partition is less than 0. PositivInfinity, if partition is greater or equal <see cref="Tiling#Partitions" />.</para>
        /// </returns>
        public override double GetMedian(int partition) {
            if (partition < 0) {
                return Double.NegativeInfinity;
            }
            if (partition >= Partitions) {
                return Double.PositiveInfinity;
            }
            double upper = _bereiche[partition];
            if (upper == Int32.MaxValue) {
                return Double.PositiveInfinity;
            }
            if (partition == 0) {
                return upper / 2.0;
            }
            else {
                double lower = _bereiche[partition - 1];
                return lower + (upper - lower) / 2.0;
            }
        }

    }
}
